package org.funtester.performance.books.chapter11.section2;

import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.results.format.ResultFormatType;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 集合遍历JMH测试
 */
@BenchmarkMode(Mode.Throughput)// 制定运行测试模式,当前为吞吐量模式
@State(value = Scope.Thread)//默认为Scope.Thread,含义是每个线程都会有一个实例
@Warmup(iterations = 1, time = 10, timeUnit = TimeUnit.SECONDS)//预热次数,含义是每个测试会跑多久
@Measurement(iterations = 1, batchSize = 1)//测试迭代次数,批次大小
@Threads(100)//测试线程数
@Fork(value = 1, jvmArgs = {"-Xms1G", "-Xmx1G"})//fork表示每个测试会fork出几个进程
@OutputTimeUnit(TimeUnit.MILLISECONDS)//输出时间单位
public class IterateSumTest {


    @Param({"1000", "10000", "100000"})//测试参数
    public int length;

    public List<Integer> nums;

    @Setup
    public void setup() {//初始化方法
        nums = new ArrayList<>(length);
        for (int i = 0; i < length; i++) {
            nums.add(i);//添加元素
        }
    }

    @Benchmark
    public int forEach() {//forEach方案
        AtomicInteger sum = new AtomicInteger();
        for (Integer num : nums) {
            sum.getAndAdd(num);//获取元素,并累加
        }
        return sum.get();
    }

    @Benchmark
    public int forIndex() {//索引方案
        AtomicInteger sum = new AtomicInteger();
        for (int i = 0; i < nums.size(); i++) {
            sum.getAndAdd(nums.get(i));//获取索引元素,并累加
        }
        return sum.get();
    }

    @Benchmark
    public int stream() {//流方案
        AtomicInteger sum = new AtomicInteger();
        nums.stream().forEach(num -> sum.addAndGet(num));//流遍历集合,并累加
        return sum.get();
    }

    @Benchmark
    public int parallelStream() {//并行流方案
        AtomicInteger sum = new AtomicInteger();
        nums.parallelStream().forEach(num -> sum.addAndGet(num));//并行流遍历集合,并累加
        return sum.get();
    }

    @Benchmark
    public int forEachLambda() {//Lambda表达式方案
        AtomicInteger sum = new AtomicInteger();
        nums.forEach(num -> sum.addAndGet(num));//Lambda表达式遍历集合,并累加
        return sum.get();
    }

    @Benchmark
    public int iterator() {//迭代器方案
        AtomicInteger sum = new AtomicInteger();
        Iterator<Integer> iterator = nums.iterator();
        while (iterator.hasNext()) {//判断是否有下一个元素
            sum.getAndAdd(iterator.next());//迭代器获取元素,并累加
        }
        return sum.get();
    }


    public static void main(String[] args) throws RunnerException {
        Options options = new OptionsBuilder()
                .include(IterateSumTest.class.getSimpleName())//测试类名
                .result("result.json")//测试结果输出到result.json文件
                .resultFormat(ResultFormatType.JSON)//输出格式
                .build();
        new Runner(options).run();
    }

}
